package xiaoqiang

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"parking-lot-go-push/logger"
	"parking-lot-go-push/model"
	"parking-lot-go-push/model/config"
	"time"
)

var xiaoQiangPushLogger = logger.NewLogger("xiaoqiang", "push")

type ResponseData struct {
	Code    int    `json:"code"`
	Data    string `json:"data"`
	Error   string `json:"error"`
	Success bool   `json:"success"`
}

// 入参格式
type ReceiveDataStruct struct {
	Data       string `json:"data"`
	Sign       string `json:"sign"`
	PlatformId string `json:"platformId"`
	Timestamp  int    `json:"timestamp"`
}

// 小强签名结构体
type XqSigner struct {
	AesKey     string
	IvParam    string
	PlatformId string
	Key        string
}

func NewSigner() *XqSigner {

	//查询小强配置
	var configXiaoqiangData config.ConfigXiaoqiangStruct
	model.GetModelDataFirst(
		model.Db,
		configXiaoqiangData.TableName(),
		&configXiaoqiangData,
		model.QueryOptions{
			Conditions: map[string]interface{}{
				"status": 1,
			},
		})

	//配置信息
	return &XqSigner{
		AesKey:     configXiaoqiangData.AesKey,
		IvParam:    configXiaoqiangData.IvParam,
		PlatformId: configXiaoqiangData.PlatFormId,
		Key:        configXiaoqiangData.Key,
	}
}

// 加密方法
func (s *XqSigner) EncryptAndSign(data map[string]interface{}) (string, string, error) {
	// 将 map 转换为 JSON 字符串
	dataJSON, err := json.Marshal(data)
	if err != nil {
		return "", "", err
	}

	xiaoQiangPushLogger.Info(fmt.Sprintf("加密串:%s", string(dataJSON)))

	// AES加密
	keyBytes := []byte(s.AesKey)
	ivBytes := []byte(s.IvParam)
	plaintext := dataJSON

	block, err := aes.NewCipher(keyBytes)
	if err != nil {
		return "", "", err
	}

	padding := aes.BlockSize - len(plaintext)%aes.BlockSize
	padText := append(plaintext, bytes.Repeat([]byte{byte(padding)}, padding)...)

	mode := cipher.NewCBCEncrypter(block, ivBytes)
	ciphertext := make([]byte, len(padText))
	mode.CryptBlocks(ciphertext, padText)

	// Base64编码
	encryptedData := base64.StdEncoding.EncodeToString(ciphertext)

	// 计算签名
	signature := s.GetSHA256(fmt.Sprintf("data=%s&platformId=%s&key=%s", encryptedData, s.PlatformId, s.Key))

	return encryptedData, signature, nil
}

// sha256加密
func (s *XqSigner) GetSHA256(str string) string {
	hasher := sha256.New()
	hasher.Write([]byte(str))
	hash := hasher.Sum(nil)
	return fmt.Sprintf("%x", hash)
}

// curl 请求
func (s *XqSigner) CurlPostJson(url string, jsonData map[string]interface{}) (err error, returnData map[string]interface{}) {

	var configXiaoqiangData config.ConfigXiaoqiangStruct
	model.GetModelDataFirst(
		model.Db,
		configXiaoqiangData.TableName(),
		&configXiaoqiangData,
		model.QueryOptions{
			Conditions: map[string]interface{}{
				"status": 1,
			},
		})

	url = configXiaoqiangData.PushBaseUrl + url
	xiaoQiangPushLogger.Info(fmt.Sprintf("推送url:%s", url))

	//追加字段
	currentTime := time.Now()
	timestamp := currentTime.UnixNano() / int64(time.Millisecond)

	jsonData["platformId"] = s.PlatformId
	jsonData["timestamp"] = timestamp

	// 将 JSON 数据封装为请求体
	jsonBytes, err := json.Marshal(jsonData)
	if err != nil {
		xiaoQiangPushLogger.Error(fmt.Sprintf("转换json失败:%s", err.Error()))
		return errors.New("转换json失败"), returnData
	}

	//推送参数
	xiaoQiangPushLogger.Info(fmt.Sprintf("data_json:%s", string(jsonBytes)))

	// 创建自定义的 HTTP 客户端
	client := &http.Client{}

	// 创建 POST 请求
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBytes))
	if err != nil {
		xiaoQiangPushLogger.Error(fmt.Sprintf("创建请求失败:%s", err.Error()))
		return errors.New("创建请求失败"), returnData
	}

	req.Header.Set("Content-Type", "application/json; charset=utf-8")

	// 发起请求
	response, err := client.Do(req)

	if err != nil {
		xiaoQiangPushLogger.Error(fmt.Sprintf("请求失败:%s", err.Error()))
		return errors.New("请求失败"), returnData
	}

	defer response.Body.Close()

	// 读取响应内容
	responseBody, err := io.ReadAll(response.Body)
	if err != nil {
		xiaoQiangPushLogger.Error(fmt.Sprintf("获取响应内容失败:%s", err.Error()))
		return errors.New("获取响应内容失败"), returnData
	}

	xiaoQiangPushLogger.Info("---- 接收小强反馈 ----")
	xiaoQiangPushLogger.Info(string(responseBody))

	var responseData ResponseData
	if err := json.Unmarshal(responseBody, &responseData); err != nil {
		xiaoQiangPushLogger.Error(fmt.Sprintf("解析响应结果失败:%s", err.Error()))
		return errors.New("解析响应结果失败"), returnData
	}

	//请求成功
	if responseData.Code == 200 {
		returnData = map[string]interface{}{
			"code":    responseData.Code,
			"data":    responseData.Data,
			"error":   responseData.Error,
			"success": responseData.Success,
		}
		return nil, returnData
	}

	return errors.New(responseData.Error), returnData
}
